package startup

import (
	"context"
	"encoding/json"
	"fmt"
	"git.mycaigou.com/gfyx/common/tenant_db"
	"git.mycaigou.com/gfyx/micro-gfyx-oppty-service/http_server/middleware"
	"git.mycaigou.com/gfyx/micro-gfyx-oppty-service/http_server/router"
	"git.mycaigou.com/gfyx/micro-gfyx-oppty-service/infrastructure/common/errcode"
	"git.mycaigou.com/gfyx/micro-gfyx-oppty-service/infrastructure/common/utils"
	"git.mycaigou.com/gfyx/micro-gfyx-oppty-service/infrastructure/di"
	aggregationPb "git.mycaigou.com/gfyx/micro-gfyx-oppty-service/proto/micro_gfyx_oppty_service_proto/micro-gfyx-oppty-service/aggregation"
	basePb "git.mycaigou.com/gfyx/micro-gfyx-oppty-service/proto/micro_gfyx_oppty_service_proto/micro-gfyx-oppty-service/base"
	businessOpportunityPb "git.mycaigou.com/gfyx/micro-gfyx-oppty-service/proto/micro_gfyx_oppty_service_proto/micro-gfyx-oppty-service/business_opportunity"
	cluePb "git.mycaigou.com/gfyx/micro-gfyx-oppty-service/proto/micro_gfyx_oppty_service_proto/micro-gfyx-oppty-service/clue"
	commonPb "git.mycaigou.com/gfyx/micro-gfyx-oppty-service/proto/micro_gfyx_oppty_service_proto/micro-gfyx-oppty-service/common"
	jobCenterPb "git.mycaigou.com/gfyx/micro-gfyx-oppty-service/proto/micro_gfyx_oppty_service_proto/micro-gfyx-oppty-service/job_center"
	marketPb "git.mycaigou.com/gfyx/micro-gfyx-oppty-service/proto/micro_gfyx_oppty_service_proto/micro-gfyx-oppty-service/market"
	rpaPb "git.mycaigou.com/gfyx/micro-gfyx-oppty-service/proto/micro_gfyx_oppty_service_proto/micro-gfyx-oppty-service/rpa"
	"git.mycaigou.com/gfyx/micro-gfyx-oppty-service/service/base/profit"
	"git.mycaigou.com/ycg/go2sky-plugins/gin/v3"
	"git.mycaigou.com/ycg/stark-extend/go2skyplugins"
	"git.mycaigou.com/ycg/stark-extend/go2skyplugins/go2skygrpc"
	"git.myscrm.cn/golang/common/ykenv"
	"git.myscrm.cn/golang/common/ykerrcode"
	"github.com/gin-gonic/gin"
	grpcMiddleware "github.com/grpc-ecosystem/go-grpc-middleware"
	grpcAuth "github.com/grpc-ecosystem/go-grpc-middleware/auth"
	grpcCtxTags "github.com/grpc-ecosystem/go-grpc-middleware/tags"
	"github.com/grpc-ecosystem/grpc-gateway/runtime"
	"google.golang.org/grpc"

	"strings"
)

// RegisterGRPCServer 此处注册pb的Server
func RegisterGRPCServer(grpcServer *grpc.Server) error {
	s := grpcServer

	inject := di.InjectInstance()
	var errs []error
	err := inject.Invoke(func(reportServer cluePb.ReportServiceServer,
		clueServer cluePb.ClueServiceServer,
		customerServer cluePb.CustomerManageServiceServer,
	) {
		cluePb.RegisterReportServiceServer(s, reportServer)
		cluePb.RegisterClueServiceServer(s, clueServer)
		cluePb.RegisterCustomerManageServiceServer(s, customerServer)
	})
	errs = append(errs, err)

	err = inject.Invoke(func(contactServer businessOpportunityPb.ContactServiceServer,
		customerServer businessOpportunityPb.CustomerServiceServer,
		commonServer businessOpportunityPb.OpptyStatusServiceServer,
		subscriptionServer businessOpportunityPb.SubscriptionServiceServer,
		orderServer businessOpportunityPb.OrderServiceServer,
		projectServer businessOpportunityPb.ProjectServiceServer,
		buildingServer businessOpportunityPb.BuildingServiceServer,
		bidServer businessOpportunityPb.BidServiceServer,
		strategicMonitorServer businessOpportunityPb.StrategicMonitorServiceServer,
	) {
		businessOpportunityPb.RegisterContactServiceServer(s, contactServer)
		businessOpportunityPb.RegisterCustomerServiceServer(s, customerServer)
		businessOpportunityPb.RegisterOpptyStatusServiceServer(s, commonServer)
		businessOpportunityPb.RegisterSubscriptionServiceServer(s, subscriptionServer)
		businessOpportunityPb.RegisterOrderServiceServer(s, orderServer)
		businessOpportunityPb.RegisterProjectServiceServer(s, projectServer)
		businessOpportunityPb.RegisterBuildingServiceServer(s, buildingServer)
		businessOpportunityPb.RegisterBidServiceServer(s, bidServer)
		businessOpportunityPb.RegisterStrategicMonitorServiceServer(s, strategicMonitorServer)
	})
	errs = append(errs, err)

	err = inject.Invoke(func(
		commonServer commonPb.OptionServiceServer,
		fileServer commonPb.FileServiceServer,
		formServer commonPb.FormServiceServer,
		dmpReportServer commonPb.DmpReportServiceServer,
		verifyCodeServer commonPb.VerifyCodeServiceServer,
	) {
		commonPb.RegisterOptionServiceServer(s, commonServer)
		commonPb.RegisterFileServiceServer(s, fileServer)
		commonPb.RegisterFormServiceServer(s, formServer)
		commonPb.RegisterDmpReportServiceServer(s, dmpReportServer) // dmp 报告
		commonPb.RegisterVerifyCodeServiceServer(s, verifyCodeServer)
	})
	errs = append(errs, err)

	err = inject.Invoke(
		func(
			baseMenuServer basePb.BaseMenuServiceServer,
			baseOrgServer basePb.BaseOrgServiceServer,
			baseMsgServer basePb.BaseMsgServiceServer,
			baseRoleServer basePb.BaseRoleServiceServer,
			baseUserService basePb.BaseUserServiceServer,
			profitService basePb.ProfitServiceServer,
			baseServer basePb.UserLoginServiceServer,
			baseAreaServer basePb.BaseAreaServiceServer,
			siteService basePb.SiteServiceServer,
		) {
			basePb.RegisterBaseMenuServiceServer(s, baseMenuServer)
			basePb.RegisterBaseOrgServiceServer(s, baseOrgServer)
			basePb.RegisterBaseMsgServiceServer(s, baseMsgServer)
			basePb.RegisterBaseRoleServiceServer(s, baseRoleServer)
			basePb.RegisterBaseUserServiceServer(s, baseUserService)
			basePb.RegisterProfitServiceServer(s, profitService)
			basePb.RegisterUserLoginServiceServer(s, baseServer)
			basePb.RegisterBaseAreaServiceServer(s, baseAreaServer)
			basePb.RegisterSiteServiceServer(s, siteService)
		})
	errs = append(errs, err)

	err = inject.Invoke(
		func(
			outboundAccountServiceServer marketPb.OutboundAccountServiceServer,
			outboundCrowdServiceServer marketPb.OutboundCrowdServiceServer,
			outboundTaskServiceServer marketPb.OutboundTaskServiceServer,
		) {
			marketPb.RegisterOutboundAccountServiceServer(s, outboundAccountServiceServer)
			marketPb.RegisterOutboundCrowdServiceServer(s, outboundCrowdServiceServer)
			marketPb.RegisterOutboundTaskServiceServer(s, outboundTaskServiceServer)
		})
	errs = append(errs, err)

	err = inject.Invoke(
		func(
			statisticsServiceServer aggregationPb.StatisticsServiceServer,
		) {
			aggregationPb.RegisterStatisticsServiceServer(s, statisticsServiceServer)
		})
	errs = append(errs, err)

	err = inject.Invoke(func(rpaConfigServer rpaPb.RpaConfigServiceServer) {
		rpaPb.RegisterRpaConfigServiceServer(s, rpaConfigServer)
	})
	errs = append(errs, err)

	err = inject.Invoke(func(rpaStartServer rpaPb.RpaStartServiceServer) {
		rpaPb.RegisterRpaStartServiceServer(s, rpaStartServer)
	})
	errs = append(errs, err)

	err = inject.Invoke(func(jobCenterServer jobCenterPb.JobCenterServiceServer) {
		jobCenterPb.RegisterJobCenterServiceServer(s, jobCenterServer)
	})
	errs = append(errs, err)
	fmt.Printf("RegisterGRPCServer errors %+v\n", errs)
	return nil
}

// RegisterGateway 此处注册pb的Gateway
func RegisterGateway(ctx context.Context, gateway *runtime.ServeMux, endPoint string, dopts []grpc.DialOption) error {
	var err error
	if err = cluePb.RegisterReportServiceHandlerFromEndpoint(ctx, gateway, endPoint, dopts); err != nil {
		return err
	}
	if err = commonPb.RegisterFormServiceHandlerFromEndpoint(ctx, gateway, endPoint, dopts); err != nil {
		return err
	}
	if err = businessOpportunityPb.RegisterContactServiceHandlerFromEndpoint(ctx, gateway, endPoint, dopts); err != nil {
		return err
	}
	if err = commonPb.RegisterOptionServiceHandlerFromEndpoint(ctx, gateway, endPoint, dopts); err != nil {
		return err
	}
	if err = basePb.RegisterBaseMenuServiceHandlerFromEndpoint(ctx, gateway, endPoint, dopts); err != nil {
		return err
	}
	if err = basePb.RegisterBaseOrgServiceHandlerFromEndpoint(ctx, gateway, endPoint, dopts); err != nil {
		return err
	}
	if err = basePb.RegisterBaseMsgServiceHandlerFromEndpoint(ctx, gateway, endPoint, dopts); err != nil {
		return err
	}
	if err = basePb.RegisterBaseRoleServiceHandlerFromEndpoint(ctx, gateway, endPoint, dopts); err != nil {
		return err
	}
	if err = basePb.RegisterBaseUserServiceHandlerFromEndpoint(ctx, gateway, endPoint, dopts); err != nil {
		return err
	}
	//if err = pb.RegisterUserServiceHandlerFromEndpoint(ctx, gateway, endPoint, dopts); err != nil {
	//	return err
	//}
	if err = basePb.RegisterBaseAreaServiceHandlerFromEndpoint(ctx, gateway, endPoint, dopts); err != nil {
		return err
	}

	if err = businessOpportunityPb.RegisterSubscriptionServiceHandlerFromEndpoint(ctx, gateway, endPoint, dopts); err != nil {
		return err
	}
	if err = businessOpportunityPb.RegisterProjectServiceHandlerFromEndpoint(ctx, gateway, endPoint, dopts); err != nil {
		return err
	}
	if err = businessOpportunityPb.RegisterBidServiceHandlerFromEndpoint(ctx, gateway, endPoint, dopts); err != nil {
		return err
	}
	if err = marketPb.RegisterOutboundCrowdServiceHandlerFromEndpoint(ctx, gateway, endPoint, dopts); err != nil {
		return err
	}

	if err = aggregationPb.RegisterStatisticsServiceHandlerFromEndpoint(ctx, gateway, endPoint, dopts); err != nil {
		return err
	}

	if err = rpaPb.RegisterRpaConfigServiceHandlerFromEndpoint(ctx, gateway, endPoint, dopts); err != nil {
		return err
	}

	if err = rpaPb.RegisterRpaStartServiceHandlerFromEndpoint(ctx, gateway, endPoint, dopts); err != nil {
		return err
	}

	return nil
}

func RegisterMiddleware() []grpc.UnaryServerInterceptor {
	myAuthFunction := func(ctx context.Context) (context.Context, error) {
		bearer, err := grpcAuth.AuthFromMD(ctx, "bearer")
		splits := strings.SplitN(bearer, ".", 2)
		if len(splits) < 2 {
			return nil, ykerrcode.TogRPCError(
				errcode.COMMON_TOKEN_ERROR, fmt.Sprintf("bearer is null, bearer: %s, err: %+v", bearer, err))
		}

		//token := splits[0]
		data := splits[1]

		authInfo := utils.AuthInfo{}
		err = json.Unmarshal([]byte(data), &authInfo)
		if err != nil {
			return nil, ykerrcode.TogRPCError(errcode.COMMON_TOKEN_ERROR, err.Error())
		}
		//
		//acUsercase := di.NewAccessTokenDi()

		// WARNING: in production define your own type to avoid context collisions
		newCtx := context.WithValue(ctx, "app_id", authInfo)
		return newCtx, nil
	}

	unaryInterceptor := grpcMiddleware.ChainUnaryServer(
		grpcCtxTags.UnaryServerInterceptor(),
		grpcAuth.UnaryServerInterceptor(myAuthFunction),
		go2skygrpc.NewUnaryServerInterceptor(),
		// 多租户拦截器
		tenant_db.TenantDBHandleGRPC,
		profit.CheckTenantProfitEffective,
	)

	return []grpc.UnaryServerInterceptor{unaryInterceptor}
}

// RegisterHttpRoute 此处注册 gin 接口
func RegisterHttpRoute(r *gin.Engine) error {
	r.Use(gin.Recovery())
	r.Use(middleware.Cors())
	r.Use(middleware.AccessLogs())

	// 链路接入
	tracer, err := go2skyplugins.GetTracer()
	if err != nil {
		fmt.Println("go2skyplugins.GetTracer err:", err.Error())
	} else {
		r.Use(v3.Middleware(r, tracer)) // r是*gin.Engine
	}

	healthGroup := r.Group("/")
	router.RegisterHealthRouters(healthGroup)
	r.Any("/", func(c *gin.Context) {
		c.JSON(0, map[string]interface{}{
			"message": "ok",
		})
	})

	if !ykenv.IsDevMode() {
		r.Use(middleware.ServiceAuthorize())
	}
	r.Use(middleware.HeaderUserInfoToMetadata())
	r.Use(middleware.TenantDb())

	commonGroup := r.Group("/v1/common")
	router.CommonRegisterRouters(commonGroup)

	return nil
}
